﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Microsoft.Health;
using Microsoft.Health.ItemTypes;
using FusionAPI;


namespace PFSync
{
    /// <summary>
    /// Summary description for Height
    /// </summary>
    public class SyncHeight : SyncItem
    {
        public SyncHeight()
        { }

        private object itemValue;

        #region Properties
        /// <summary>
        /// Returns a hashcode that is the unique ID for this item
        /// </summary>
        public override int ID
        {
            get
            {
                int hashCode = DateAdded.GetHashCode();
                hashCode += Value.GetHashCode();
                hashCode += Measurement.GetHashCode();

                return hashCode;
            }
        }

        /// <summary>
        /// Generate a HealthVault item based on the Value,
        /// Date, and Measurements stored in this object
        /// </summary>
        public override HealthRecordItem HVItem
        {
            get
            {
                DisplayValue value;

                Height item = new Height();
                item.When = new HealthServiceDateTime(DateAdded);

                // Get the display value to store based on the measurement type
                if (Measurement == MeasurementType.Meters)
                    value = new DisplayValue(Convert.ToDouble(itemValue), "m", "m");
                else
                    value = new DisplayValue(Convert.ToDouble(Value), "inches", "in");

                // Store the item's value based on itemValue (meters) and the display value
                item.Value = new Length(Convert.ToDouble(itemValue), value);
                item.CommonData.Note = "Synced from Patient Fusion";

                return item;
            }
        }

        /// <summary>
        /// Generate a PracticeFusion item based on the Value,
        /// Date, and Measurements stored in this object
        /// </summary>
        public override ClinicalDataValue PFItem
        {
            get
            {
                ClinicalDataValue item = new ClinicalDataValue();
                item.CollectedDateTime = DateAdded.ToUniversalTime();
                item.Value = (Convert.ToDouble(Value) * 100).ToString();
                item.Source = "PatientFusion Sync";
                item.ID = PFTypeId;

                return item;
            }
        }

        /// <summary>
        /// Return the Practice Fusion TypeID
        /// </summary>
        public override int PFTypeId
        {
            get 
            {
                if (Measurement == MeasurementType.Meters)
                    return 76;
                else
                    return 75; 
            }
        }

        /// <summary>
        /// Return the HealthVault Type GUID
        /// </summary>
        public override Guid HVTypeID
        {
            get { return Height.TypeId; }
        }

        /// <summary>
        /// Gets the Height value in Meters (double) or Inches (int) depending 
        /// on MeasurementType. Value that is -set- only takes in meters.
        /// </summary>
        public override object Value
        {
            get
            {
                // If MeasurementType equals Meters, return value (double)
                if (Measurement == MeasurementType.Meters)
                    return itemValue;

                // Else, return the value in inches (int)
                else
                    return Math.Round(Convert.ToDouble(itemValue) * 39.3700787);
            }

            // Only takes in meters for a value
            set { itemValue = value; }
        }

        /// <summary>
        /// Gets and sets the object's measurement type
        /// </summary>
        public override MeasurementType Measurement { get; set; }

        /// <summary>
        /// Gets and sets the object's Date
        /// </summary>
        public override DateTime DateAdded { get; set; }
#endregion

        /// <summary>
        /// Default constructor takes in a date, value and measurement
        /// </summary>
        /// <param name="date">Date Added</param>
        /// <param name="value">Value of Height</param>
        /// <param name="measurement">Height Measurement</param>
        public SyncHeight(DateTime date, double value, MeasurementType measurement)
        {
            DateAdded = date;
            Measurement = measurement;
            
            // If the measurement is in inches, convert to meters
            if (measurement == MeasurementType.Inches)
                itemValue = value * 0.0254;
            else
                itemValue = value;
        }

        /// <summary>
        /// Constructor takes in a HealthVault height item
        /// and converts it to a PFSync item.
        /// </summary>
        /// <param name="hvRecord">HealthVault Height</param>
        public SyncHeight(Height hvRecord)
        {
            DateAdded = hvRecord.When.ToDateTime();
            Value = hvRecord.Value.Meters;

            // Check to see if the value given is in meters or inches
            if (hvRecord.Value.DisplayValue == null || hvRecord.Value.DisplayValue.UnitsCode == "m")
                Measurement = MeasurementType.Meters;
            else
                Measurement = MeasurementType.Inches;
        }

        /// <summary>
        /// Constructor takes in a PracticeFusion Record and a
        /// measurement type and converts it to a PFSync Item
        /// </summary>
        /// <param name="pfRecord">PracticeFusion Record</param>
        /// <param name="measurement">Measurement Type</param>
        public SyncHeight(ClinicalDataValue pfRecord, MeasurementType measurement)
        {
            DateAdded = pfRecord.CollectedDateTime.ToLocalTime();
            Measurement = measurement;

            // If the measurement type is in meters, convert to centimeters
            if (measurement == MeasurementType.Meters)
                Value = double.Parse(pfRecord.Value) / 100.0;
            else
                Value = int.Parse(pfRecord.Value) * 0.0254;
        }
    }
}
